package org.hyh.core.log;

import lombok.extern.slf4j.Slf4j;
import oracle.jdbc.internal.OraclePreparedStatement;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.executor.parameter.ParameterHandler;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis.scripting.defaults.DefaultParameterHandler;
import org.springframework.stereotype.Component;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.util.List;
import java.util.Properties;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @author :yihui.He
 * @description :  拦截{@link ParameterHandler#setParameters(PreparedStatement)}方法，从而得到将要执行的sql.
 * @date :2021/2/18
 */
@Intercepts({
    @Signature(type = ParameterHandler.class,method = "setParameters",args = {PreparedStatement.class})
})
//@Component
@Slf4j
public class SqlLogInterceptor  implements Interceptor {
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        ParameterHandler handler= (ParameterHandler)invocation.getTarget();
        Object[] args = invocation.getArgs();

        //  根据不同的statement 来实现获取对应的sql
        PreparedStatement preparedStatement= (PreparedStatement)args[0];
        Object result = invocation.getMethod().invoke(handler, args);
        Connection connection = preparedStatement.getConnection();
        // 获取driveClassName
        // connection.getMetaData().getDriverName()
        if (preparedStatement.isWrapperFor(com.mysql.jdbc.PreparedStatement.class)) {
            com.mysql.jdbc.PreparedStatement unwrap = preparedStatement.unwrap(com.mysql.jdbc.PreparedStatement.class);
            String sql = unwrap.asSql();
            if (!sql.contains("\n")) {
//                log.info("\n sql==>{}", sql);
                System.err.println("\n sql:"+sql);
            }else {
                String[] split = sql.split("\n");
                Object[] objects = Stream.of(split).map(String::trim).toArray();
//                log.info("\n sql==>{}",StringUtils.join(objects,"  "));
                System.err.println("\n sql:"+StringUtils.join(objects,"  "));

            }

        } else if (preparedStatement.isWrapperFor(oracle.jdbc.internal.OraclePreparedStatement.class)) {
            OraclePreparedStatement statement = preparedStatement.unwrap(OraclePreparedStatement.class);
            String originalSql = statement.getOriginalSql();
            log.info("\n sql==>{}",originalSql);

        }

        return result ;
    }

    @Override
    public Object plugin(Object target) {
        if (target instanceof ParameterHandler) {
            return Plugin.wrap(target, this);
        }
        return  target;


    }

    @Override
    public void setProperties(Properties properties) {

    }
}
